<!-- 表单 》 下拉框 -->

<template>
  <el-form-item v-bind="formItem">
    <!-- 标签 -->
    <template v-if="hasLabelSlot" #label>
      <slot name="label" :label="formItem.label">{{ formItem.label }}</slot>
    </template>

    <div :class="`${className}-flex`">
      <!-- 前缀 -->
      <span v-if="hasPrefix" :class="`${className}-prefix`">
        <slot name="prefix">{{ prefix }}</slot>
      </span>

      <el-select
        v-model="model"
        v-bind="commonProps"
        :popperClass="popperClass"
        :filterable="!noSearch"
        :clearable="!noClear && !initFirst"
        @change="emitChange"
      >
        <el-option
          v-for="(item, i) in selectData"
          :key="`${item[0]}-${i}`"
          :class="getHideClass(item)"
          :value="item[0]"
          :label="item[1]"
          :disabled="getDisabled(item)"
        >
          <div class="CoreWeb-option">
            <slot name="item" :item="item">
              <div>{{ item[1] }}</div>
              <div v-if="showRight" class="CoreWeb-option-right">{{ item[rightIndex] }}</div>
            </slot>
          </div>
        </el-option>
      </el-select>

      <!-- 后缀 -->
      <span v-if="hasSuffix" :class="`${className}-suffix`">
        <slot name="suffix">{{ suffix }}</slot>
      </span>
    </div>
  </el-form-item>
</template>

<script>
// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import mixForm from '../mixForm'
import FormInput from '../FormInput'

const name = 'FormSelect'

// ============================== 导出组件 ============================== //

export default {
  /**
   * 名称定义 (实际使用名称)
   */
  name,

  /**
   * 混入列表 (配置选项合并)
   */
  mixins: [mixForm],

  /**
   * 属性注册 (抽取以便查阅)
   */
  props: CORE.WEB[name],

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    ...FormInput.computed,

    /**
     * 是否显示右侧辅助信息
     */
    showRight() {
      const { hasRight, rightIndex, dict } = this
      return hasRight && rightIndex > 1 && dict[0] && dict[0].length > rightIndex
    },

    /**
     * 下拉框数据
     */
    selectData() {
      const { functionType, functionIndex, itemPre, itemSuf } = this
      const dict = (this.dict || []).map(([id, name, ...other]) => [id, `${itemPre}${name || ''}${itemSuf}`, ...other])
      if (functionType !== 'none') return dict
      return dict.filter((item) => !(CORE.isFunction(item[functionIndex]) && item[functionIndex]()))
    },

    /**
     * 弹出层样式类
     */
    popperClass() {
      const { elProps: { popperClass = '' }, double, triple } = this
      const doubleStr = double ? ' CoreWeb-option-double' : ''
      const tripleStr = triple ? ' CoreWeb-option-triple' : ''
      return `${popperClass}${doubleStr}${tripleStr}`
    },
  },

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    /**
     * 是否不等 (可覆盖)
     */
    isDiff() {
      const { obj, prop, bindList, isMulti, model, init, EMPTY, initFirst, selectData } = this
      const value = obj[prop]
      const values = selectData.find(([id]) => value === id)

      // 判断是否存在有效值字典
      if (values) {
        // 不相等
        if (value !== model) return true
        // 相等且 bind 不是数组
        if (!isMulti) return false
        // bind 的所有属性都需要相等
        return bindList.some((key, i) => obj[key.trim()] !== values[i] || (i ? '' : EMPTY))
      } else if (initFirst && selectData.length) return true
      else return model !== EMPTY || value !== (init || EMPTY)
    },

    /**
     * 设置内部绑定值 (可覆盖)
     */
    setModel() {
      const { obj, prop, initFirst, selectData, init, EMPTY } = this
      const value = obj[prop]
      const values = selectData.find(([id]) => value === id)

      // 判断是否存在有效值字典
      if (values) this.model = value
      else if (initFirst && selectData.length) this.model = selectData[0][0]
      else this.model = init || EMPTY
    },

    /**
     * 是否物理相等 (如不等可直接用 value 赋值给 obj[bind] ) (可覆盖)
     */
    equals(value) {
      const { obj, prop, bindList, isMulti, selectData, EMPTY } = this

      if (isMulti) {
        const values = selectData.find((item) => item[0] === value) || []
        return bindList.every((key, i) => obj[key.trim()] === values[i] || (i ? '' : EMPTY))
      } else {
        return obj[prop] === value
      }
    },

    /**
     * 获取隐藏样式类
     */
    getHideClass(item) {
      const { functionType, functionIndex } = this
      const itemFun = item[functionIndex]
      const hasHide = functionType === 'hide' && CORE.isFunction(itemFun) && itemFun()
      return hasHide ? 'CoreWeb-WebForm-item-hide' : null
    },

    /**
     * 获取是否禁用
     */
    getDisabled(item) {
      const { isDisabled, grayed, functionType, functionIndex } = this
      if (isDisabled || grayed.some((id) => `${id}` === `${item[0]}`)) return true

      const itemFun = item[functionIndex]
      return functionType === 'gray' && CORE.isFunction(itemFun) && itemFun()
    },

    /**
     * 清除选中
     */
    toClear() {
      this.model = this.EMPTY
      this.emitChange()
    },
  },
}
</script>
